在 Spring 中配置特定的内存数据库用于测试目的
Configure specific in memory database for testing purpose in Spring
如何配置我的 Spring 引导应用程序,以便当我 运行 单元测试时它将使用内存数据库,例如 H2/HSQL 但是当我 运行 Spring 启动应用程序它将使用生产数据库 [Postgre/MySQL] ?
Spring 配置文件可用于此。这将是一个具体的方式:
具有特定于环境的属性文件:
application.properties:
spring.profiles.active: dev
申请-dev.properties
spring.jpa.database: MYSQL
spring.jpa.hibernate.ddl-auto: update
spring.datasource.url: jdbc:mysql://localhost:3306/dbname
spring.datasource.username: username
spring.datasource.password: password
应用-test.properties
spring.jpa.database: HSQL
在pom.xml
中同时拥有MySQL和H2驱动程序,像这样:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>
最后但同样重要的是,用 @ActiveProfiles("test")
.
注释测试 类
@Sanjay 有一种表达方式,但我觉得它很混乱。您也可以只拥有一个在生产中启用的 production
配置文件,例如:
spring.jpa.hibernate.ddl-auto: update
spring.datasource.url: jdbc:mysql://localhost:3306/dbname
spring.datasource.username: username
spring.datasource.password: password
并且不要指定任何其他内容。如果您在 test
范围内添加一个嵌入式数据库,它将在您的测试中可用。如果您 运行 使用默认配置文件(没有任何自定义)进行测试,它将找不到任何数据库信息(因为这些信息存储在 production
配置文件中)。在这种情况下,它会尝试找到一个嵌入式数据库并为您启动它。如果您出于某种原因需要更多自定义,您可以为这些设置 application-test.properties
(您需要将 ActiveProfiles("test")
添加到您的测试中)。
使用 maven
构建的简单解决方案:只需将 application.properties
文件放在 src/test/resources
下并根据需要进行编辑以进行测试。
Spring(引导)配置文件机制是一个非常强大的工具,其范围远远超出 "swapping settings between test time and run time"。虽然,很明显,正如所展示的那样,它也可以做到这一点 :)
另一种方法是将注释@AutoConfigureTestDatabase
添加到您的测试class。
我的测试通常是这样的:
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
public class MyRepositoryTest {
@Autowired
MyRepository repository;
@Test
public void test() throws Exception {
// Tests...
}
}
注意需要在pom.xml文件中添加内嵌数据库依赖。
对于嵌入式数据库,此注释不是必需的,即使只在 pom 文件中添加依赖项,它也会起作用。
最简单的解决方案:
1) 在 src/main/resources 中有 application.properties(生产配置):
spring.datasource.url=jdbc:mysql://localhost:3306/somedb
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.jpa.database-platform = org.hibernate.dialect.MySQL5Dialect
和应用程序-test.properties,HSQL 配置如下:
spring.jpa.hibernate.ddl-auto = create-drop
spring.jpa.database = HSQL
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.HSQLDialect
spring.datasource.driverClassName = org.hsqldb.jdbcDriver
spring.datasource.url= jdbc:hsqldb:mem:scratchdb
spring.datasource.username = sa
spring.datasource.password =
2) 如果您还没有 HSQL 依赖项,请在 pom.xml 中添加它。
3) 用 @ActiveProfiles("test").
注释你的测试 class
对我来说很有魅力。
使用@SpringBootTest 魔法,您只需要做以下两个更改。
- 在pom.xml
中添加'h2'测试依赖
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MySpringBootApplication.class)
@AutoConfigureTestDatabase
public class SpringBootTest{
@Autowired
private RequestRepository requestRepository;
}
现在测试中使用的所有spring jpa bean/repositories都将使用h2作为后备数据库。
2019-04-26 13:13:34.198 INFO 28627 --- [ main]
beddedDataSourceBeanFactoryPostProcessor : Replacing 'dataSource'
DataSource bean with embedded version
2019-04-26 13:13:34.199 INFO 28627 --- [ main]
o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition
for bean 'dataSource'
2019-04-26 13:13:36.194 INFO 28627 --- [ main]
o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database:
url='jdbc:h2:mem:2784768e-f053-4bb3-ab88-edda34956893;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false',
username='sa'
注意:我仍然在 'application.properties' 中定义了 'spring-jpa' 属性,并且我没有使用任何配置文件。 @AutoConfigureTestDatabase 将使用测试默认值 AutoConfigureTestDatabase.Replace.
覆盖现有的 jpa 配置
此解决方案支持开发和测试的通用设置。基于此解决方案:
在 Junit 测试中覆盖默认 Spring-Boot application.properties 设置
- application.properties 在 src/main/resources/application.properties
#common settings for DEVELOPMENT and TEST:
......
......
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url=jdbc:postgresql://localhost:5432/databasename
spring.datasource.username=postgres
spring.datasource.password=somepassword
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = none
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
- test.properties (src/main/resources/application.properties) 覆盖并添加 application.properties 中的属性:
spring.datasource.url=jdbc:h2:mem:testdb;MODE=PostgreSQL
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=update
spring.h2.console.enabled=false
- pom.xml 中针对 H2 和 Postgre 数据库的设置
<!-- h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- postgress -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
- 在测试中class:
@RunWith(SpringRunner.class)
@SpringBootTest
@TestPropertySource(locations = "classpath:test.properties")
public class ModelTest {
}
我有一个多模块 Gradle SpringBootApplication 具有以下模块
- employeemanagerApp - 我的 SpringApplication main class
- employeemanagerIntTests - 我在哪里进行黄瓜测试
我的要求是在应用程序启动时使用 MySQL 数据库,在我的 Cucumber 集成测试期间使用 H2
解决方案: 在我的 employeemanagerApp 模块中,src/main/resources 我放置了具有以下内容的 application.properties
#My SQL Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/employeemanager
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
并且在集成测试模块 (employeemanagerIntTests) src/test/resources 中我放置了 application.properties 内容如下
#H2 In-Memory DB Configuration
spring.datasource.url=jdbc:h2://mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.format_sql=true
并且在我的步骤定义中 Class 我只添加了这些注释
@CucumberContextConfiguration
@SpringBootTest(classes = SpringBootApplicationMainClass.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
在 build.gradle 文件中我添加了 H2 依赖项
testImplementation 'com.h2database:h2:1.4.200'
因此,当我 运行 我的测试时,H2 处于活动状态并且所有具有创建、更新、读取和删除的测试都成功了
如何配置我的 Spring 引导应用程序,以便当我 运行 单元测试时它将使用内存数据库,例如 H2/HSQL 但是当我 运行 Spring 启动应用程序它将使用生产数据库 [Postgre/MySQL] ?
Spring 配置文件可用于此。这将是一个具体的方式:
具有特定于环境的属性文件:
application.properties:
spring.profiles.active: dev
申请-dev.properties
spring.jpa.database: MYSQL
spring.jpa.hibernate.ddl-auto: update
spring.datasource.url: jdbc:mysql://localhost:3306/dbname
spring.datasource.username: username
spring.datasource.password: password
应用-test.properties
spring.jpa.database: HSQL
在pom.xml
中同时拥有MySQL和H2驱动程序,像这样:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>
最后但同样重要的是,用 @ActiveProfiles("test")
.
@Sanjay 有一种表达方式,但我觉得它很混乱。您也可以只拥有一个在生产中启用的 production
配置文件,例如:
spring.jpa.hibernate.ddl-auto: update
spring.datasource.url: jdbc:mysql://localhost:3306/dbname
spring.datasource.username: username
spring.datasource.password: password
并且不要指定任何其他内容。如果您在 test
范围内添加一个嵌入式数据库,它将在您的测试中可用。如果您 运行 使用默认配置文件(没有任何自定义)进行测试,它将找不到任何数据库信息(因为这些信息存储在 production
配置文件中)。在这种情况下,它会尝试找到一个嵌入式数据库并为您启动它。如果您出于某种原因需要更多自定义,您可以为这些设置 application-test.properties
(您需要将 ActiveProfiles("test")
添加到您的测试中)。
使用 maven
构建的简单解决方案:只需将 application.properties
文件放在 src/test/resources
下并根据需要进行编辑以进行测试。
Spring(引导)配置文件机制是一个非常强大的工具,其范围远远超出 "swapping settings between test time and run time"。虽然,很明显,正如所展示的那样,它也可以做到这一点 :)
另一种方法是将注释@AutoConfigureTestDatabase
添加到您的测试class。
我的测试通常是这样的:
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
public class MyRepositoryTest {
@Autowired
MyRepository repository;
@Test
public void test() throws Exception {
// Tests...
}
}
注意需要在pom.xml文件中添加内嵌数据库依赖。 对于嵌入式数据库,此注释不是必需的,即使只在 pom 文件中添加依赖项,它也会起作用。
最简单的解决方案:
1) 在 src/main/resources 中有 application.properties(生产配置):
spring.datasource.url=jdbc:mysql://localhost:3306/somedb
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.jpa.database-platform = org.hibernate.dialect.MySQL5Dialect
和应用程序-test.properties,HSQL 配置如下:
spring.jpa.hibernate.ddl-auto = create-drop
spring.jpa.database = HSQL
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.HSQLDialect
spring.datasource.driverClassName = org.hsqldb.jdbcDriver
spring.datasource.url= jdbc:hsqldb:mem:scratchdb
spring.datasource.username = sa
spring.datasource.password =
2) 如果您还没有 HSQL 依赖项,请在 pom.xml 中添加它。
3) 用 @ActiveProfiles("test").
注释你的测试 class对我来说很有魅力。
使用@SpringBootTest 魔法,您只需要做以下两个更改。
- 在pom.xml 中添加'h2'测试依赖
<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>test</scope> </dependency>
@RunWith(SpringRunner.class) @SpringBootTest(classes = MySpringBootApplication.class) @AutoConfigureTestDatabase public class SpringBootTest{ @Autowired private RequestRepository requestRepository; }
现在测试中使用的所有spring jpa bean/repositories都将使用h2作为后备数据库。
2019-04-26 13:13:34.198 INFO 28627 --- [ main] beddedDataSourceBeanFactoryPostProcessor : Replacing 'dataSource' DataSource bean with embedded version
2019-04-26 13:13:34.199 INFO 28627 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'dataSource'
2019-04-26 13:13:36.194 INFO 28627 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url='jdbc:h2:mem:2784768e-f053-4bb3-ab88-edda34956893;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
注意:我仍然在 'application.properties' 中定义了 'spring-jpa' 属性,并且我没有使用任何配置文件。 @AutoConfigureTestDatabase 将使用测试默认值 AutoConfigureTestDatabase.Replace.
覆盖现有的 jpa 配置此解决方案支持开发和测试的通用设置。基于此解决方案: 在 Junit 测试中覆盖默认 Spring-Boot application.properties 设置
- application.properties 在 src/main/resources/application.properties
#common settings for DEVELOPMENT and TEST:
......
......
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url=jdbc:postgresql://localhost:5432/databasename
spring.datasource.username=postgres
spring.datasource.password=somepassword
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = none
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
- test.properties (src/main/resources/application.properties) 覆盖并添加 application.properties 中的属性:
spring.datasource.url=jdbc:h2:mem:testdb;MODE=PostgreSQL
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=update
spring.h2.console.enabled=false
- pom.xml 中针对 H2 和 Postgre 数据库的设置
<!-- h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- postgress -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
- 在测试中class:
@RunWith(SpringRunner.class)
@SpringBootTest
@TestPropertySource(locations = "classpath:test.properties")
public class ModelTest {
}
我有一个多模块 Gradle SpringBootApplication 具有以下模块
- employeemanagerApp - 我的 SpringApplication main class
- employeemanagerIntTests - 我在哪里进行黄瓜测试
我的要求是在应用程序启动时使用 MySQL 数据库,在我的 Cucumber 集成测试期间使用 H2
解决方案: 在我的 employeemanagerApp 模块中,src/main/resources 我放置了具有以下内容的 application.properties
#My SQL Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/employeemanager
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
并且在集成测试模块 (employeemanagerIntTests) src/test/resources 中我放置了 application.properties 内容如下
#H2 In-Memory DB Configuration
spring.datasource.url=jdbc:h2://mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.format_sql=true
并且在我的步骤定义中 Class 我只添加了这些注释
@CucumberContextConfiguration
@SpringBootTest(classes = SpringBootApplicationMainClass.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
在 build.gradle 文件中我添加了 H2 依赖项
testImplementation 'com.h2database:h2:1.4.200'
因此,当我 运行 我的测试时,H2 处于活动状态并且所有具有创建、更新、读取和删除的测试都成功了